//! 函数类型(函)和用户自定义对象类型(物)实现
//!
//! 设计原则：
//! - 函数：可调用对象，支持参数验证、返回值类型检查
//! - 对象：用户自定义类型，支持属性、方法、继承

use crate::ast::{ASTNode, Param};
use crate::interpreter::method::{Method, MethodType};
use crate::interpreter::value::{Value, ValueData};
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;

/// 函数类型(函)的实现
#[derive(Clone)]
pub struct FunctionType {
    /// 函数名称
    pub name: String,
    /// 参数列表
    pub parameters: Vec<Param>,
    /// 函数体
    pub body: Vec<ASTNode>,
    /// 闭包环境
    pub closure: Rc<RefCell<HashMap<String, Value>>>,
    /// 返回类型（可选）
    pub return_type: Option<String>,
    /// 是否原生函数
    pub is_native: bool,
    /// 原生函数实现
    pub native_impl: Option<fn(&[Value]) -> Result<Value, String>>,
}

impl FunctionType {
    /// 创建新的用户定义函数
    pub fn new(
        name: String,
        parameters: Vec<Param>,
        body: Vec<ASTNode>,
        closure: Rc<RefCell<HashMap<String, Value>>>,
        return_type: Option<String>,
    ) -> Self {
        Self {
            name,
            parameters,
            body,
            closure,
            return_type,
            is_native: false,
            native_impl: None,
        }
    }

    /// 创建新的原生函数
    pub fn native(
        name: String,
        parameters: Vec<Param>,
        return_type: Option<String>,
        implementation: fn(&[Value]) -> Result<Value, String>,
    ) -> Self {
        Self {
            name,
            parameters,
            body: vec![],
            closure: Rc::new(RefCell::new(HashMap::new())),
            return_type,
            is_native: true,
            native_impl: Some(implementation),
        }
    }

    /// 验证参数数量
    pub fn validate_argument_count(&self, args: &[Value]) -> Result<(), String> {
        let expected_count = self.parameters.len();
        let actual_count = args.len();

        if actual_count != expected_count {
            return Err(format!(
                "函数 '{}' 需要 {} 个参数，但提供了 {} 个",
                self.name, expected_count, actual_count
            ));
        }

        Ok(())
    }

    /// 验证参数类型（如果指定了类型）
    pub fn validate_argument_types(&self, _args: &[Value]) -> Result<(), String> {
        // 简化实现：暂时不进行类型验证
        Ok(())
    }

    /// 类型兼容性检查（简化版本）
    fn is_type_compatible(&self, expected_type: &str, value: &Value) -> bool {
        let actual_type = value.get_type_name();

        // 精确匹配
        if expected_type == actual_type {
            return true;
        }

        // 数字类型兼容性
        if expected_type == "数" && (actual_type == "数" || actual_type == "整数") {
            return true;
        }

        // 字符串类型兼容性
        if expected_type == "文" && actual_type == "文" {
            return true;
        }

        // 布尔类型兼容性
        if expected_type == "真伪" && actual_type == "真伪" {
            return true;
        }

        // 列表类型兼容性
        if expected_type == "集" && actual_type == "集" {
            return true;
        }

        // 字典类型兼容性
        if expected_type == "辞" && actual_type == "辞" {
            return true;
        }

        // 集合类型兼容性
        if expected_type == "汇" && actual_type == "汇" {
            return true;
        }

        // 元组类型兼容性
        if expected_type == "组" && actual_type == "组" {
            return true;
        }

        // 函数类型兼容性
        if expected_type == "函" && actual_type == "函" {
            return true;
        }

        // 对象类型兼容性
        if expected_type == "物" && actual_type == "物" {
            return true;
        }

        // 空值兼容性
        if expected_type == "无" && actual_type == "无" {
            return true;
        }

        false
    }

    /// 验证返回值类型（如果指定了返回类型）
    pub fn validate_return_type(&self, value: &Value) -> Result<(), String> {
        if let Some(return_type) = &self.return_type {
            if !self.is_type_compatible(return_type, value) {
                return Err(format!(
                    "函数 '{}' 返回值类型不匹配：期望 '{}', 实际为 '{}'",
                    self.name,
                    return_type,
                    value.get_type_name()
                ));
            }
        }
        Ok(())
    }

    /// 获取函数签名
    pub fn get_signature(&self) -> String {
        let params: Vec<String> = self.parameters.iter().map(|p| p.name.clone()).collect();

        let return_part = if let Some(rt) = &self.return_type {
            format!(" -> {}", rt)
        } else {
            "".to_string()
        };

        format!("函 {}({}){}", self.name, params.join(", "), return_part)
    }

    /// 转换为字符串表示
    pub fn to_string(&self) -> String {
        if self.is_native {
            format!("<原生函数: {}>", self.name)
        } else {
            format!("<函数: {}>", self.name)
        }
    }
}

/// 函数类型(函)的方法实现
pub struct FunctionMethods;

impl FunctionMethods {
    /// 创建函数类型的所有内置方法
    pub fn create_all_methods() -> HashMap<String, Method> {
        let mut methods = HashMap::new();

        // 基本信息方法
        methods.insert("名称".to_string(), Self::create_name_method());
        methods.insert("参数数".to_string(), Self::create_param_count_method());
        methods.insert("返回类型".to_string(), Self::create_return_type_method());
        methods.insert("签名".to_string(), Self::create_signature_method());
        methods.insert("是原生".to_string(), Self::create_is_native_method());

        // 转换方法
        methods.insert("转字符串".to_string(), Self::create_to_string_method());

        methods
    }

    /// 创建名称方法
    fn create_name_method() -> Method {
        Method::native(MethodType::String, |args| {
            if let ValueData::Function {
                params: _,
                body: _,
                closure: _,
                return_type: _,
            } = &args[0].data
            {
                // 简化处理：函数名称未知，返回默认值
                Ok(Value::string("函数".to_string()))
            } else {
                Err("不是函数类型".to_string())
            }
        })
    }

    /// 创建参数数方法
    fn create_param_count_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Function {
                params,
                body: _,
                closure: _,
                return_type: _,
            } = &args[0].data
            {
                Ok(Value::number(params.len() as f64))
            } else {
                Err("不是函数类型".to_string())
            }
        })
    }

    /// 创建返回类型方法
    fn create_return_type_method() -> Method {
        Method::native(MethodType::String, |args| {
            if let ValueData::Function {
                params: _,
                body: _,
                closure: _,
                return_type,
            } = &args[0].data
            {
                // 返回函数的返回类型信息
                match return_type {
                    Some(rt) => Ok(Value::string(rt.clone())),
                    None => Ok(Value::string("无".to_string())),
                }
            } else {
                Err("不是函数类型".to_string())
            }
        })
    }

    /// 创建签名方法
    fn create_signature_method() -> Method {
        Method::native(MethodType::String, |args| {
            if let ValueData::Function {
                params,
                body: _,
                closure: _,
                return_type: _,
            } = &args[0].data
            {
                let param_count = params.len();
                let signature = format!("函({} 个参数)", param_count);
                Ok(Value::string(signature))
            } else {
                Err("不是函数类型".to_string())
            }
        })
    }

    /// 创建是原生方法
    fn create_is_native_method() -> Method {
        Method::native(MethodType::Boolean, |args| {
            if let ValueData::Function {
                params: _,
                body: _,
                closure: _,
                return_type: _,
            } = &args[0].data
            {
                // ValueData::Function 没有原生标记，假设都不是原生
                Ok(Value::boolean(false))
            } else {
                Err("不是函数类型".to_string())
            }
        })
    }

    /// 创建转字符串方法
    fn create_to_string_method() -> Method {
        Method::native(MethodType::String, |args| {
            if let ValueData::Function {
                params: _,
                body: _,
                closure: _,
                return_type: _,
            } = &args[0].data
            {
                Ok(Value::string("<函>".to_string()))
            } else {
                Err("不是函数类型".to_string())
            }
        })
    }
}

/// 对象类型(物)的方法实现
pub struct ObjectMethods;

impl ObjectMethods {
    /// 创建对象类型的所有内置方法
    pub fn create_all_methods() -> HashMap<String, Method> {
        let mut methods = HashMap::new();

        // 基本信息方法
        methods.insert("名称".to_string(), Self::create_name_method());
        methods.insert("字段数".to_string(), Self::create_field_count_method());
        methods.insert("方法数".to_string(), Self::create_method_count_method());
        methods.insert("字段名".to_string(), Self::create_field_names_method());
        methods.insert("方法名".to_string(), Self::create_method_names_method());

        // 字段操作方法
        methods.insert("获取字段".to_string(), Self::create_get_field_method());
        methods.insert("设置字段".to_string(), Self::create_set_field_method());
        methods.insert("有字段".to_string(), Self::create_has_field_method());
        methods.insert("有方法".to_string(), Self::create_has_method_method());

        // 继承相关方法
        methods.insert("父类".to_string(), Self::create_parent_method());
        methods.insert("是子类".to_string(), Self::create_is_subclass_method());

        // 转换方法
        methods.insert("转字符串".to_string(), Self::create_to_string_method());

        methods
    }

    /// 创建名称方法
    fn create_name_method() -> Method {
        Method::native(MethodType::String, |args| {
            if let ValueData::Object(fields) = &args[0].data {
                let obj_fields = fields.borrow();
                let name = obj_fields
                    .get("name")
                    .and_then(|v| {
                        if let ValueData::String(s) = &v.data {
                            Some(s.clone())
                        } else {
                            None
                        }
                    })
                    .unwrap_or("对象".to_string());
                Ok(Value::string(name))
            } else {
                Err("不是对象类型".to_string())
            }
        })
    }

    /// 创建字段数方法
    fn create_field_count_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Object(fields) = &args[0].data {
                Ok(Value::number(fields.borrow().len() as f64))
            } else {
                Err("不是对象类型".to_string())
            }
        })
    }

    /// 创建方法数方法
    fn create_method_count_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Object(fields) = &args[0].data {
                let obj_fields = fields.borrow();
                let methods_count = obj_fields
                    .get("methods")
                    .and_then(|v| {
                        if let ValueData::Dict(methods) = &v.data {
                            Some(methods.borrow().len())
                        } else {
                            None
                        }
                    })
                    .unwrap_or(0);
                Ok(Value::number(methods_count as f64))
            } else {
                Err("不是对象类型".to_string())
            }
        })
    }

    /// 创建字段名方法
    fn create_field_names_method() -> Method {
        Method::native(MethodType::List, |args| {
            if let ValueData::Object(fields) = &args[0].data {
                let obj_fields = fields.borrow();
                let names: Vec<Value> = obj_fields
                    .keys()
                    .map(|name| Value::string(name.to_string()))
                    .collect();
                Ok(Value::list(names))
            } else {
                Err("不是对象类型".to_string())
            }
        })
    }

    /// 创建方法名方法
    fn create_method_names_method() -> Method {
        Method::native(MethodType::List, |args| {
            if let ValueData::Object(fields) = &args[0].data {
                let obj_fields = fields.borrow();
                let method_names = obj_fields
                    .get("methods")
                    .and_then(|v| {
                        if let ValueData::Dict(methods) = &v.data {
                            Some(methods.borrow().keys().cloned().collect::<Vec<String>>())
                        } else {
                            None
                        }
                    })
                    .unwrap_or_default();
                let names: Vec<Value> = method_names
                    .iter()
                    .map(|name| Value::string(name.to_string()))
                    .collect();
                Ok(Value::list(names))
            } else {
                Err("不是对象类型".to_string())
            }
        })
    }

    /// 创建获取字段方法
    fn create_get_field_method() -> Method {
        Method::native(MethodType::Any, |args| {
            if let (ValueData::Object(fields), ValueData::String(field_name)) =
                (&args[0].data, &args[1].data)
            {
                let obj_fields = fields.borrow();
                match obj_fields.get(field_name) {
                    Some(value) => Ok(value.clone()),
                    None => Ok(Value::null()),
                }
            } else {
                Err("获取字段方法需要对象和字符串参数".to_string())
            }
        })
    }

    /// 创建设置字段方法
    fn create_set_field_method() -> Method {
        Method::native(MethodType::Object, |args| {
            if let (ValueData::Object(fields), ValueData::String(field_name)) =
                (&args[0].data, &args[1].data)
            {
                if args.len() < 3 {
                    return Err("设置字段方法需要字段名和值参数".to_string());
                }

                let mut obj_fields = fields.borrow_mut();
                obj_fields.insert(field_name.clone(), args[2].clone());
                Ok(args[0].clone())
            } else {
                Err("设置字段方法需要对象、字符串和值参数".to_string())
            }
        })
    }

    /// 创建有字段方法
    fn create_has_field_method() -> Method {
        Method::native(MethodType::Boolean, |args| {
            if let (ValueData::Object(fields), ValueData::String(field_name)) =
                (&args[0].data, &args[1].data)
            {
                let obj_fields = fields.borrow();
                Ok(Value::boolean(obj_fields.contains_key(field_name)))
            } else {
                Err("有字段方法需要对象和字符串参数".to_string())
            }
        })
    }

    /// 创建有方法方法
    fn create_has_method_method() -> Method {
        Method::native(MethodType::Boolean, |args| {
            if let (ValueData::Object(fields), ValueData::String(method_name)) =
                (&args[0].data, &args[1].data)
            {
                let obj_fields = fields.borrow();
                let has_method = obj_fields
                    .get("methods")
                    .and_then(|v| {
                        if let ValueData::Dict(methods) = &v.data {
                            Some(methods.borrow().contains_key(method_name))
                        } else {
                            None
                        }
                    })
                    .unwrap_or(false);
                Ok(Value::boolean(has_method))
            } else {
                Err("有方法方法需要对象和字符串参数".to_string())
            }
        })
    }

    /// 创建父类方法
    fn create_parent_method() -> Method {
        Method::native(MethodType::Any, |args| {
            if let ValueData::Object(fields) = &args[0].data {
                let obj_fields = fields.borrow();
                let parent = obj_fields.get("parent");
                match parent {
                    Some(_) => {
                        // 这里简化处理，实际应该返回父对象
                        Ok(Value::null())
                    }
                    None => Ok(Value::null()),
                }
            } else {
                Err("不是对象类型".to_string())
            }
        })
    }

    /// 创建是子类方法
    fn create_is_subclass_method() -> Method {
        Method::native(MethodType::Boolean, |args| {
            if let (ValueData::Object(fields), ValueData::String(parent_name)) =
                (&args[0].data, &args[1].data)
            {
                let obj_fields = fields.borrow();
                let name = obj_fields
                    .get("name")
                    .and_then(|v| {
                        if let ValueData::String(s) = &v.data {
                            Some(s.clone())
                        } else {
                            None
                        }
                    })
                    .unwrap_or("对象".to_string());

                // 简化处理：检查对象名称是否包含父类名称
                Ok(Value::boolean(name.contains(parent_name)))
            } else {
                Err("是子类方法需要对象和字符串参数".to_string())
            }
        })
    }

    /// 创建转字符串方法
    fn create_to_string_method() -> Method {
        Method::native(MethodType::String, |args| {
            if let ValueData::Object(fields) = &args[0].data {
                let obj_fields = fields.borrow();
                let name = obj_fields
                    .get("name")
                    .and_then(|v| {
                        if let ValueData::String(s) = &v.data {
                            Some(s.clone())
                        } else {
                            None
                        }
                    })
                    .unwrap_or("对象".to_string());
                Ok(Value::string(format!("<对象: {}>", name)))
            } else {
                Err("不是对象类型".to_string())
            }
        })
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_function_methods_creation() {
        let methods = FunctionMethods::create_all_methods();

        // 检查基本信息方法是否存在
        assert!(methods.contains_key("名称"));
        assert!(methods.contains_key("参数数"));
        assert!(methods.contains_key("返回类型"));
        assert!(methods.contains_key("签名"));
        assert!(methods.contains_key("是原生"));

        // 检查转换方法是否存在
        assert!(methods.contains_key("转字符串"));
    }

    #[test]
    fn test_object_methods_creation() {
        let methods = ObjectMethods::create_all_methods();

        // 检查基本信息方法是否存在
        assert!(methods.contains_key("名称"));
        assert!(methods.contains_key("字段数"));
        assert!(methods.contains_key("方法数"));
        assert!(methods.contains_key("字段名"));
        assert!(methods.contains_key("方法名"));

        // 检查字段操作方法是否存在
        assert!(methods.contains_key("获取字段"));
        assert!(methods.contains_key("设置字段"));
        assert!(methods.contains_key("有字段"));
        assert!(methods.contains_key("有方法"));

        // 检查继承相关方法是否存在
        assert!(methods.contains_key("父类"));
        assert!(methods.contains_key("是子类"));

        // 检查转换方法是否存在
        assert!(methods.contains_key("转字符串"));
    }

    #[test]
    fn test_function_type_creation() {
        let func = FunctionType::new(
            "测试函数".to_string(),
            vec![],
            vec![],
            Rc::new(RefCell::new(HashMap::new())),
            Some("数".to_string()),
        );

        assert_eq!(func.name, "测试函数");
        assert_eq!(func.return_type, Some("数".to_string()));
        assert!(!func.is_native);
    }
}
